#include "Graphics.h"
#include <math.h>

using namespace WONAPI;

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Graphics::Graphics()
{
	mTransX = mTransY = 0;
	mColorScheme = NULL;
	mColor = 0;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Graphics::~Graphics()
{
	Detach();
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::Detach()
{
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::Attach(DisplayContext *theContext)
{
	Detach();
	mColor = 0;
	mDisplayContext = theContext;
	mDisplayContext->mGraphics = this;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::SetColor(DWORD theColor)
{
	if(theColor>=0x80000000 && theColor<0x80000000+StandardColor_Max && mColorScheme)
	{
		// Do it this way instead of calling ApplyColorSchemeColor in order to avoid an infinite loop
		// If a colorscheme color is a reference to itself
		DWORD aColor = mColorScheme->GetStandardColor((StandardColor)(theColor-0x80000000));
		if(aColor!=mColor)
		{
			mColor = aColor;
			SetColorHook();
		}
	}
	else if(mColor!=theColor)
	{
		mColor = theColor;
		SetColorHook();
	}
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
DWORD Graphics::GetColorSchemeColor(StandardColor theColorRef)
{
	if(mColorScheme)
		return mColorScheme->GetStandardColor(theColorRef);
	else
		return 0;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::ApplyColorSchemeColor(StandardColor theColorRef)
{
	if(mColorScheme)
		SetColor(mColorScheme->GetStandardColor(theColorRef));
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::Translate(int dx, int dy)
{
	mTransX += dx;
	mTransY += dy;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DoTranslate(int &x, int &y)
{
	x+=mTransX;
	y+=mTransY;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
DWORD Graphics::GetPixel(int x, int y)
{
	DoTranslate(x,y);
	return GetPixelHook(x,y);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::SetPixel(int x, int y, DWORD theColor)
{
	DoTranslate(x,y);
	SetPixelHook(x,y,theColor);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawImage(Image *theImage, int x, int y)
{
	DoTranslate(x,y);
	theImage->DrawEntire(mDisplayContext,x,y);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawImage(Image *theImage, int x, int y, int left, int top, int width, int height)
{
	DoTranslate(x,y);
	theImage->Draw(mDisplayContext, x, y, left, top, width, height);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawLine(int x1, int y1, int x2, int y2)
{

	DoTranslate(x1,y1);
	DoTranslate(x2,y2);

	DrawLineHook(x1,y1,x2,y2);	
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawRect(int x, int y, int width, int height)
{
	DoTranslate(x,y);
	DrawRectHook(x,y,width,height);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillRect(int x, int y, int width, int height)
{
	DoTranslate(x,y);
	FillRectHook(x,y,width,height);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillRectBlend(int x, int y, int width, int height, int theBlendAmount)
{
	DoTranslate(x,y);
	FillRectBlendHook(x,y,width,height,theBlendAmount);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawDottedRect(int x, int y, int width, int height)
{
	DoTranslate(x,y);
	DrawDottedRectHook(x,y,width,height);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawEllipse(int x, int y, int width, int height)
{
	DoTranslate(x,y);
	DrawEllipseHook(x,y,width,height);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillEllipse(int x, int y, int width, int height)
{
	DoTranslate(x,y);
	FillEllipseHook(x,y,width,height);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawPolygon(POINT thePoints[], int nPoints)
{
	int i;
	for(i=0; i<nPoints; i++)
	{
		thePoints[i].x += mTransX;
		thePoints[i].y += mTransY;
	}

	DrawPolygonHook(thePoints,nPoints);

	for(i=0; i<nPoints; i++)
	{
		thePoints[i].x -= mTransX;
		thePoints[i].y -= mTransY;
	}	
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillPolygon(POINT thePoints[], int nPoints)
{
	int i;
	for(i=0; i<nPoints; i++)
	{
		thePoints[i].x += mTransX;
		thePoints[i].y += mTransY;
	}

	FillPolygonHook(thePoints,nPoints);

	for(i=0; i<nPoints; i++)
	{
		thePoints[i].x -= mTransX;
		thePoints[i].y -= mTransY;
	}
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
{
	DoTranslate(x,y);
	DrawArcHook(x,y,width,height,startAngle,arcAngle);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::SetFont(Font *theFont)
{
	if(theFont!=mFont)
	{
		mFont = theFont;
		mFont->PrepareContext(mDisplayContext);
	}
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawString(const GUIString &theStr, int x, int y)
{
	DoTranslate(x,y);
	mFont->DrawString(mDisplayContext,theStr,0,theStr.length(),x, y);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawString(const GUIString &theStr, unsigned short theOffset, unsigned short theLength, int x, int y)
{
	DoTranslate(x,y);
	mFont->DrawString(mDisplayContext,theStr,theOffset,theLength,x, y);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawString(const char *theStr, int theLen, int x, int y)
{
	DoTranslate(x,y);
	mFont->DrawString(mDisplayContext, GUIString(theStr,theLen), 0, theLen, x, y);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::GetClipRectWithTrans(WONRectangle &theRect)
{
	theRect = mClipRect;
	theRect.x -= mTransX;
	theRect.y -= mTransY;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::PerformClip()
{
	ClearClipRectHook();
	mClipRect.x = mClipRect.y = -10000000;
	mClipRect.width = mClipRect.height = 20000001;
	if(mClipStack.empty())
		return;

	WONRectangle aRect = mClipStack.front();
	ClipStack::iterator anItr = mClipStack.begin();
	++anItr;

	while(anItr!=mClipStack.end())
	{
		aRect.DoIntersect(*anItr);
		++anItr;
	}

	SetClipRectHook(aRect.Left(), aRect.Top(), aRect.Width(), aRect.Height());
	mClipRect = aRect;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::PushClipRect(int x, int y, int width, int height)
{
	DoTranslate(x,y);
	WONRectangle aRect(x , y, width, height);
	mClipStack.push_back(aRect);
	PerformClip();
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::PopClipRect()
{
	if(!mClipStack.empty())
		mClipStack.pop_back();

	PerformClip();

}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawLineHook(int x1, int y1, int x2, int y2)
{
	
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawRectHook(int x, int y, int width, int height)
{
	DrawLineHook(x,y,x+width,y);
	DrawLineHook(x+width,y,x+width,y+height);
	DrawLineHook(x+width,y+height,x,y+height);
	DrawLineHook(x,y+height,x,y);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawDottedRectHook(int x, int y, int width, int height)
{
//	DrawRectHook(x,y,width,height);
	int i;
	for(i=0; i<width; i+=2)
	{
		SetPixelHook(x+i,y,mColor);
		SetPixelHook(x+i,y+height-1,mColor);
	}

	for(i=0; i<height; i+=2)
	{
		SetPixelHook(x,y+i,mColor);
		SetPixelHook(x+width-1,y+i,mColor);
	}
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillRectHook(int x, int y, int width, int height)
{
	for(int i=0; i<height; i++)
		DrawLineHook(x,y+i,x+width,y+i);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillRectBlendHook(int x, int y, int width, int height, int theBlendAmount)
{
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawPolygonHook(POINT thePoints[], int nPoints)
{
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillPolygonHook(POINT thePoints[], int nPoints)
{
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawEllipseHook(int x, int y, int width, int height)
{
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::FillEllipseHook(int x, int y, int width, int height)
{
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Graphics::DrawArcHook(int x, int y, int width, int height, int startAngle, int arcAngle)
{
}
